<?php

namespace common\components;

use cebe\markdown\GithubMarkdown;
use yii\helpers\Html;

class FireLoongMarkdown extends GithubMarkdown
{
    /**
     * Default Codepen theme ID
     */
    protected $theme;

    public function __construct($theme = false)
    {

        /**
         * Set the default theme ID
         */
        $this->theme = $theme;

    }

    /**
     * Consume lines for a headline
     */
    protected function consumeHeadline($lines, $current)
    {
        if ($lines[$current][0] === '#') {
            // ATX headline
            $level = 1;
            while (isset($lines[$current][$level]) && $lines[$current][$level] === '#' && $level < 6) {
                $level++;
            }
            $block = [
                'headline',
                'content' => $this->parseInline(trim($lines[$current], "# \t")),
                'level' => $level,
                'current' => $current
            ];
            return [$block, $current];
        } else {
            // underlined headline
            $block = [
                'headline',
                'content' => $this->parseInline($lines[$current]),
                'level' => $lines[$current + 1][0] === '=' ? 1 : 2,
                'current' => $current
            ];
            return [$block, $current + 1];
        }
    }

    /**
     * Renders a headline
     * @param array $block
     * @return string
     */
    protected function renderHeadline($block)
    {
        $tag = 'h' . $block['level'];
        $content = $this->renderAbsy($block['content']);
        return Html::tag($tag, $content, ['id' => '_' . ($block['current'] + 1)]);
    }

    /**
     * 引用块标识
     * @param string $line
     * @return bool
     */
    protected function identifyQuoteRank($line)
    {
        $matches = false;
        $regex = "/^>(?:\[(default|info|warning|success|danger)\])(?:\[(left|right)\])?/";
        preg_match($regex, $line, $matches);
        if (isset($matches[1])) {
            $level = $line[strlen($matches[1]) + 3];
            if (!isset($level) || $level === ' ' || $level === "\t") {
                return true;
            } elseif (isset($matches[2])) {
                $reverse = $line[strlen($matches[1] . $matches[2]) + 5];
                if (!isset($reverse) || $reverse === ' ' || $reverse === "\t") {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 定义引用块信息
     * @param array $lines
     * @param int $current
     * @return array
     */
    protected function consumeQuoteRank($lines, $current)
    {
        $string = rtrim($lines[$current]);
        $matches = false;
        $regex = "/^>(?:\[(default|info|warning|success|danger)\])(?:\[(left|right)\])?/";
        preg_match($regex, $string, $matches);
        $content = [];
        for ($i = $current, $count = count($lines); $i < $count; $i++) {
            $line = $lines[$i];
            if (ltrim($line) !== '') {
                if ($line[0] == '>' && !isset($line[1])) {
                    $line = '';
                } elseif (strncmp($line, '>[' . $matches[1] . ']', strlen($matches[1]) + 3) === 0 && !isset($matches[2])) {
                    $line = substr($line, strlen($matches[1]) + 3);
                } elseif (isset($matches[2]) && strncmp($line, '>[' . $matches[1] . '][' . $matches[2] . ']', strlen($matches[1] . $matches[2]) + 5) === 0) {
                    $line = substr($line, strlen($matches[1] . $matches[2]) + 5);
                }
                $content[] = $line;
            } else {
                break;
            }
        }

        $block = [
            'quoteRank',
            'content' => $this->parseBlocks($content),
            'level' => false,
            'reverse' => false
        ];


        $block['level'] = $matches[1];
        if (isset($matches[2])) {
            $block['reverse'] = $matches[2];
        }
        return [$block, $i];
    }

    /**
     * 显示引用块
     * @param array $block
     * @return string
     */
    protected function renderQuoteRank($block)
    {
        $reverseClass = $block['reverse'] == 'right' ? ' blockquote-reverse' : '';
        return '<blockquote class="blockquote-' . $block['level'] . $reverseClass . '">' . $this->renderAbsy($block['content']) . '</blockquote>';
    }

    /**
     * Codepen identifier
     * @param $line
     * @param $lines
     * @param $current
     * @return bool
     */
    protected function identifyCodepen($line, $lines, $current)
    {
        if (strncmp($line, 'codepen[', 8) === 0) {
            return true;
        }
        return false;
    }

    /**
     * Codepen Consumer
     *
     * @param array $lines All lines in document
     * @param int $current Current line
     * @return array            An array of a block and linenumber to continue consuming
     */
    protected function consumeCodepen($lines, $current)
    {
        $block = [
            'Codepen',
            'content' => [],
            'pen' => false,
            'height' => false,
            'tab' => false,
            'theme' => false
        ];

        $line = rtrim($lines[$current]);
        $matches = false;

        /**
         * Regular expression that matches:
         *  - A string starting with "codepen"
         *  The pen identifier    - A string of alpha characters minimum of 4 characters and maximum of 8, between brackets.
         *  The height of the pen - An integer with a minimum length of 2 and maximum of 5, between brackets.
         *  The active tab        - (optional) A string equal to one of four options; 'html', 'css', 'js' or 'result', between brackets.
         *  The theme for the pen - (optional) An integer with a minimum length of 1 and a maximum of 6, between brackets.
         */
        $regex = "/^codepen(?:\[([A-z]{4,8})\])(?:\[(\d{2,5})\])(?:\[(html|css|js|result)\])?(?:\[(\d{1,6})\])?$/";
        preg_match($regex, $line, $matches);

        if (count($matches) < 3) return [$block, $current++];

        $block['pen'] = $matches[1];
        $block['height'] = $matches[2];

        if (isset($matches[3])) {
            $block['tab'] = $matches[3];
        }
        if (isset($matches[4])) {
            $block['theme'] = $matches[4];
        }

        return [$block, $current++];
    }

    /**
     * Codepen Renderer
     *
     * @param array $block
     * @return string            HTML that should be rendered
     */
    protected function renderCodepen($block)
    {
        if (!isset($block['pen'])) return false;

        $pen = $block['pen'];
        $height = $block['height'];
        $tab = 'result';
        $theme = $this->theme;

        if ($block['tab']) {
            $tab = $block['tab'];
        }

        if ($block['theme']) {
            $theme = $block['theme'];
        }

        return "<p data-height='{$height}' data-slug-hash='{$pen}' data-default-tab='{$tab}' data-theme-id='{$theme}' class='codepen'></p>";
    }
}